home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / ddj0897.zip / RCSC.ZIP / PACKAGES / SC22.ZIP / AR.C next >
C/C++ Source or Header  |  1988-01-25  |  9KB  |  353 lines

  1. /* 
  2. **   AR -- File Archiver
  3. **
  4. **   usage: ar -{dptux} arcfile [file...]
  5. **
  6. **   Ar collects text files into a single archive file.
  7. **   Files can be extracted, new ones added,
  8. **   old ones replaced or deleted, and
  9. **   a list of the archive contents produced.
  10. **
  11. **   The first argument is a switch from the following set.
  12. **   The second argument is the name of the archive file.
  13. **   The third and subsequent arguments are file names. 
  14. **
  15. **   -d  delete named files from the library.
  16. **   -p  print named, or all, files on stdout.
  17. **   -t  table of contents of named, or all, files to stdout.
  18. **   -u  update the archive by adding/replacing files
  19. **       (used to create a new library).
  20. **       If no file names are specified in the command line,
  21. **       they are obtained from stdin.
  22. **   -x  extract named, or all, files.
  23. **
  24. **   Control-S to pause execution and control-C to abort.
  25. **
  26. **   This program was given as a class assignment in the
  27. **   Computer Science Department at the University of Arizona.
  28. **   It was contributed by Ernext Payne.  Orignially it was
  29. **   written to work with tape archives, but this version has
  30. **   been modified for higher speed operation with diskette
  31. **   archives under CP/M.
  32. */
  33.  
  34. #include <stdio.h>
  35.  
  36. #define NAMESIZE 30
  37. #define MAXLINE  500
  38. #define MAXFILES 20
  39. #define HDR      ">>>"
  40. #define AUXSIZE  4096
  41.  
  42. char tname[]="  ar.$$$";
  43. int fnptr[MAXFILES];
  44. int fstat[MAXFILES];
  45. int nfiles;
  46. int errchk;
  47.  
  48. main(argc, argv) int argc, argv[]; {
  49.   char cmd[3], aname[NAMESIZE];
  50.   if(getarg(1,  cmd,       3,argc,argv) == EOF) usage();
  51.   if(getarg(2,aname,NAMESIZE,argc,argv) == EOF) usage();
  52.   if(aname[1] == ':') {
  53.     tname[0] = aname[0];
  54.     tname[1] = aname[1];
  55.     }
  56.   else left(tname);
  57.   getfns(argc,argv);
  58.   switch(toupper(cmd[1])) {
  59.     case 'D': drop(aname);
  60.               break;
  61.     case 'T': table(aname);
  62.               break;
  63.     case 'U': update(aname);
  64.               break;
  65.     case 'X':
  66.     case 'P': extract(aname, toupper(cmd[1]));
  67.               break;
  68.      default: usage();
  69.     }
  70.   }
  71.  
  72. /* acopy - copy size characters from fpi to fpo */
  73. acopy(fpi,fpo,size) int fpi, fpo; int size; {
  74.   int c;
  75.   while(size-- > 0) {
  76.     poll(YES);
  77.     if((c = getc(fpi)) == EOF)
  78.       break;
  79.     putc(c,fpo);
  80.     }
  81.   }
  82.  
  83. /* addfile - add file "name" to archive */
  84. addfile(name,fp) char *name; int fp; {
  85.   int nfp;
  86.   if((nfp = fopen(name,"r")) == NULL) {
  87.     fprintf(stderr,"%s: can't open\n",name);
  88.     errchk = 1;
  89.     }
  90.   if (errchk == 0) {
  91.     if(name[1] == ':') name += 2;
  92.     fprintf(fp,"%s %s %d\n",HDR,name,fsize(nfp));
  93.     fcopy(nfp,fp);
  94.     fclose(nfp);
  95.     fprintf(stderr, " copied new %s\n", name);
  96.     }
  97.   }
  98.  
  99. /* amove - move file1 to file2 */
  100. amove(file1,file2) char *file1, *file2; {
  101.   if(errchk) {
  102.     printf("fatal errors - archive not altered\n");
  103.     unlink(file1);
  104.     exit(7);
  105.     }
  106.   unlink(file2);
  107.   if(file2[1] == ':') file2 += 2;
  108.   if(rename(file1, file2)) {
  109.     printf("can't rename %s to %s\n", file1, file2);
  110.     exit(7);
  111.     }
  112.   }
  113.  
  114. /* cant - print file name and die */
  115. cant(name) char *name; {
  116.   fprintf(stderr,"%s: can't open\n",name);
  117.   exit(7);
  118.   }
  119.  
  120. /* drop - delete files from archive */
  121. drop(aname) char *aname; {
  122.   int afp, tfp;
  123.   if(nfiles <= 0) /* protect innocents  */
  124.     error("delete by name only");
  125.   afp = mustopen(aname,"r");
  126.   tfp = mustopen(tname,"w");
  127.   auxbuf(tfp, AUXSIZE);
  128.   replace(afp,tfp,'d');
  129.   notfound();
  130.   fclose(afp);
  131.   fclose(tfp);
  132.   amove(tname,aname);
  133.   }
  134.  
  135. /* error - print message and die */
  136. error(msg) char *msg; {
  137.   fprintf(stderr,"%s\n",msg);
  138.   exit(7);
  139.   }
  140.  
  141. /* extract - extract files from archive */
  142. extract(aname,cmd) char *aname, cmd; {
  143.   int afp, efp;
  144.   char ename[NAMESIZE], in[MAXLINE];
  145.   int size;
  146.   afp = mustopen(aname,"r");
  147.   auxbuf(afp, AUXSIZE);
  148.   if(cmd == 'P') efp = stdout;
  149.   else           efp = NULL;
  150.   while((size = gethdr(afp,in,ename)) >= 0)
  151.     if(!fmatch(ename, YES)) fskip(afp,size);
  152.     else {
  153.       if(efp != stdout) efp = fopen(ename,"w");
  154.       if(efp == NULL) {
  155.         fprintf(stderr,"%s: can't create\n",ename);
  156.         errchk = 1;
  157.         fskip(afp,size);
  158.         }
  159.       else {
  160.         if(cmd == 'P') {
  161.           fprintf(efp, "\n───────────────────────────────────");
  162.           fprintf(efp, "───────────────────────────────────\n");
  163.           fprintf(efp, "                               %s", ename);
  164.           fprintf(efp, "\n───────────────────────────────────");
  165.           fprintf(efp, "───────────────────────────────────\n");
  166.           }
  167.         acopy(afp,efp,size);
  168.         if(cmd == 'P') fprintf(stderr, "printed %s\n", ename);
  169.         else           fprintf(stderr, "created %s\n", ename);
  170.         if(efp != stdout) fclose(efp);
  171.         }
  172.       }
  173.   notfound();
  174.   fclose(afp);
  175.   }
  176.  
  177. /* fcopy - copy file in to file out */
  178. fcopy(in,out) int in, out; {
  179.   int c;
  180.   while((c = getc(in)) != EOF) {
  181.     poll(YES);
  182.     putc(c,out);
  183.     }
  184.   }
  185.  
  186. /* fmatch - check if name matches argument list */
  187. fmatch(name, quit) char *name; int quit; {
  188.   int i, done;
  189.   char *fnp;
  190.   if(nfiles <= 0) return(1);
  191.   done = YES;
  192.   for(i=0;i<nfiles;++i) {
  193.     fnp = fnptr[i];
  194.     if(fnp[1] == ':') fnp += 2;
  195.     if(same(name,fnp) == 0) {
  196.       fstat[i] = 1;
  197.       return(1);
  198.       }
  199.     if(fstat[i] == 0) done = NO;
  200.     }
  201.   if(quit && done) exit(0);
  202.   return(0);
  203.   }
  204.  
  205. /* fsize - size of file in characters */
  206. fsize(fp) int fp; {
  207.   int i;
  208.   for(i=0; getc(fp) != EOF; ++i) ;
  209.   rewind(fp);
  210.   return(i);
  211.   }
  212.  
  213. /* fskip - skip n characters on file fp */
  214. fskip(fp,n) int fp, n; {
  215.   while(n-- > 0) {
  216.     poll(YES);
  217.     if(fgetc(fp) == EOF) break;
  218.     }
  219.   }
  220.  
  221. /* getfns - get file names into fname, check for duplicates */
  222. getfns(argc,argv) int argc, argv[]; {
  223.   int i, j;
  224.   nfiles = argc - 3;
  225.   if(nfiles > MAXFILES)
  226.     error("too many file names");
  227.   for(i=0,j=3; i<nfiles; i++,j++)
  228.     fnptr[i] = argv[j];
  229.   for(i = 0; i < nfiles-1; ++i)
  230.     for(j = i+1; j < nfiles; ++j) {
  231.       if(same(fnptr[i],fnptr[j]) == 0) {
  232.         fprintf(stderr,"%s:duplicate file names\n",fnptr[i]);
  233.         exit(7);
  234.         }
  235.     }
  236.   }
  237.  
  238. /* gethdr - get header info from fp */
  239. gethdr(fp,buf,name) int fp; char *buf, *name; {
  240.   if(fgets(buf,MAXLINE,fp) == NULL)
  241.     return(-1);
  242.   buf = getwrd(buf,name);
  243.   if(strcmp(name,HDR) != 0)
  244.     error("archive not in proper format");
  245.   buf = getwrd(buf,name);
  246.   return(atoi(buf));
  247.   }
  248.  
  249. /* getwrd - copy first word of s to t */
  250. getwrd(s,t) char *s, *t; {
  251.   while(isspace(*s)) ++s;
  252.   while(*s != '\0' && !isspace(*s))  *t++ = *s++;
  253.   *t = '\0';
  254.   return(s);
  255.   }
  256.  
  257. /* mustopen - open file or die */
  258. mustopen(name,mode) char *name, *mode; {
  259.   int fp;
  260.   if(fp = fopen(name,mode)) return(fp);
  261.   cant(name);
  262.   }
  263.  
  264. /* notfound - print "not found" message */
  265. notfound() {
  266.   int i;
  267.   for(i=0;i<nfiles;++i)
  268.     if(fstat[i] == 0) {
  269.       fprintf(stderr,"%s not in archive\n",fnptr[i]);
  270.       errchk = 1;
  271.     }
  272.   }
  273.  
  274. /* replace - replace or delete files */
  275. replace(afp,tfp,cmd) int afp, tfp; char cmd; {
  276.   char in[MAXLINE], uname[NAMESIZE];
  277.   int size;
  278.   while((size = gethdr(afp,in,uname)) >= 0) {
  279.     if(fmatch(uname, NO)) {
  280.       if(cmd == 'u')    /* add new one */
  281.         addfile(uname,tfp);
  282.       fskip(afp,size);  /* discard old one */
  283.       fprintf(stderr, "dropped old %s\n", uname);
  284.       }
  285.     else {
  286.       fputs(in,tfp);
  287.       acopy(afp,tfp,size);
  288.       }
  289.     }
  290.   }
  291.  
  292. /* table - print table of archive contents  */
  293. table(aname) char *aname; {
  294.   char in[MAXLINE], lname[NAMESIZE];
  295.   int afp, size;
  296.   afp = mustopen(aname,"r");
  297.   while((size = gethdr(afp,in,lname)) >= 0) {
  298.     poll(YES);
  299.     if(fmatch(lname, YES)) printf("%s\n", lname);
  300.     fskip(afp,size);
  301.     }
  302.   notfound();
  303.   fclose(afp);
  304.   }
  305.  
  306. /* update - update existing files, add new ones at end */
  307. update(aname) char *aname; {
  308.   int afp, i, tfp;
  309.   char fn[NAMESIZE];
  310.   if((afp = fopen(aname,"r+")) == NULL)
  311.     /* maybe archive does not exist yet */
  312.     afp = mustopen(aname,"w+");
  313.   tfp = mustopen(tname,"w+");
  314.   auxbuf(tfp, AUXSIZE);
  315.   replace(afp,tfp,'u');   /* update existing */
  316.   if(nfiles > 0) {
  317.     for(i=0;i<nfiles;++i) /* add new ones */
  318.       if(fstat[i] == 0) {
  319.         addfile(fnptr[i],tfp);
  320.         if(errchk) break;
  321.         fstat[i] = 1;
  322.         }
  323.     }
  324.   else
  325.     while(1) {
  326.       poll(YES);
  327.       if(iscons(stdin)) fprintf(stdout,"file - ");
  328.       if(!fgets(fn, NAMESIZE, stdin) || *fn == '\n') break;
  329.       for(i=0; fn[i]; i++)
  330.         if((fn[i] = toupper(fn[i])) == '\n') fn[i] = NULL;
  331.       addfile(&fn[0], tfp);
  332.       if(errchk) break;
  333.       }
  334.   fclose(afp);
  335.   fclose(tfp);
  336.   amove(tname,aname);
  337.   }
  338.  
  339. /* return <0,   0,  >0 according to s<t, s=t, s>t*/
  340. same(s, t) char *s, *t; {
  341.   while(toupper(*s) == toupper(*t)) {
  342.     if(toupper(*s) == 0) return (0);
  343.     ++s; ++t;
  344.     }
  345.   return (toupper(*s) - toupper(*t));
  346.   }
  347.  
  348. /* usage - abort with a usage message */
  349. usage() {
  350.   error("usage: ar -{dptux} arcfile [file...]");
  351.   }
  352.  
  353.